export function getProperty(entities: any[], propertyName = 'id', pipe?: (element: object) => any) {
    const ids = entities.map(value => {
        let element = value[propertyName];
        if (pipe) {
            element = pipe(element)
        }
        return element;
    }).filter(Boolean);
    return [...new Set(ids)];
}

type Match = (dbEntity: any, entity: any) => boolean;

type SetValue = (dbEntity: object, entity: any) => any;
type SetValues = (dbEntity: object[], entity: any) => any;


export function setProperty(
    entities: object[],
    dbEntities: object[],
    match: Match,
    set: SetValue,
    notFoundProcess?: (entity: any) => void,
    moreMatchAndSet: { match: Match, set: SetValue }[] = []
) {
    function process(entity: object, index: number, match: Match, set: SetValue) {
        const dbEntity = dbEntities.find(dbEntity => match(dbEntity, entity));
        if (dbEntity) {
            const r = set(dbEntity, entity);
            if (r) {
                entities[index] = r;
            }
        } else if (notFoundProcess) {
            notFoundProcess(entity);
        }
    }

    for (let i = 0; i < entities.length; i++) {
        let entity = entities[i];
        process(entity, i, match, set);
        if (moreMatchAndSet?.length > 0) {
            for (let {match, set} of moreMatchAndSet) {
                process(entity, i, match, set)
            }
        }
    }
}

export function setProperties(
    entities: any[],
    dbEntities: any[],
    match: Match,
    set: SetValues,
) {
    for (let entity of entities) {
        const filter = dbEntities.filter(dbEntity => match(dbEntity, entity));
        set(filter, entity)
    }
}
